#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "buffer.h"
#include "leveldb/options.h"

namespace leveldb {
    int *array;    
    std::string key_prefix("for_test_key-");
    std::string key_postfix("00000000");
    std::string value_prefix("for_test_value-");
    
    int prepare(int count) {
	int i ;
	array = (int *)malloc(count * sizeof(int));
	for(i = 0; i < count; i ++) {
	    array[ i ] = i;
	}

	for(i = 0; i < count; i ++) {
	    int rand = (random() % count);
	    int tmp = array[i];
	    array[i] = array[rand];
	    array[rand] = tmp;
	}
	return 0;
    }
    
int insert_test(Buffer *buffer, int count) {
    std::string key, value;
    int i;
    char tmp[10];
    printf("start insert test: \n");
    for(i = 0; i < count; i ++) {
	key.assign(key_prefix);
	snprintf(tmp, 10, "%08d", array[i]);
	key.append(tmp, 8);
	key.append(key_postfix);
	value.assign(value_prefix);
	value.append(1024, 'v');
	int ret = buffer->Insert(Slice(key.c_str(), key.size()),
				 Slice(value.c_str(), value.size()));
	if(ret == -1) {
	    printf("Insert error: %s\n", key.c_str());
	}
    }

    printf("end insert\n\n");
    return 0;
}

int get_test(Buffer *buffer, int count) {
    std::string key, value;
    int i, missing = 0;
    char tmp[10];
    printf("start get test: \n");
    for(i = 0; i < count; i ++) {
	key.assign(key_prefix);
	snprintf(tmp, 10, "%08d", array[i]);
	key.append(tmp, 8);
	key.append(key_postfix);	
	Status s = buffer->Get(Slice(key.c_str(), key.size()), &value);
	if(!s.ok()) {
	    missing ++;
	    printf("Get error: %s\n", key.c_str());
	}
    }

    printf("missing %d\n", missing);
    printf("end get\n\n");
    return 0;
}

int erase_test(Buffer *buffer, int count) {
    std::string key;
    int i;

    printf("start erase test\n");
    for(i = 0; i < count; i ++) {
	key.assign(key_prefix);
	key.append(key_postfix);	
	buffer->Erase(Slice(key.c_str(), key.size()));
    }
    printf("end erase \n\n");
    
    return 0;
}

int iter_test(Buffer* buffer, int count) {
    Slice start("for_test_key-");
    Slice end("for_test_key-9999999999");
    Options options;
    InternalKeyComparator comparator(options.comparator);
    Iterator *iter = buffer->NewIterator(start, end);
    iter->SeekToFirst();
    std::string str, last;
    int c = 0;
    printf("start iter test\n");
    while(iter->Valid()) {
	c ++;
	str.assign(iter->key().data(), iter->key().size());
	if(last.empty()) {
	    last = str;
	}
	if(comparator.Compare(Slice(str), Slice(last)) < 0) {
	    printf("Error!\n");
	    assert(0);
	}
	last = str;
//	printf("%s\n", str.c_str());
	iter->Next();
    }
    delete iter;
    printf("end iter, count: %d\n\n", c);

    return 0;
}

int run_test(int count) {
    Options options;
    Buffer buffer("/home/zzg/data", 0);
    
    prepare(count);
    insert_test(&buffer, count);
    get_test(&buffer, count);
    iter_test(&buffer, count);
//    erase_test(&buffer, count);
//    get_test(&buffer, count);

    return 0;
} 
}

int num = 200000;
int main(int argc, char **argv) {
    leveldb::run_test(num);
    return 0;
}
